home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / program / commio0b.zip / SYSKEYS.PAS < prev    next >
Pascal/Delphi Source File  |  1996-05-14  |  13KB  |  321 lines

  1. unit SysKeys;
  2. {
  3.           This unit is a companion to the COMMIO communications unit.
  4.                 Written by Jason Morriss a.k.a. Lief O'Pardy
  5.  
  6.                   Copyright (C) 1995,1996 by Jason Morriss
  7.  
  8.  
  9.   This is the Sysop Function key unit.  This unit allows you to create
  10.   procedures that will get called automatically when the sysop presses a
  11.   Function Key (F1-F12) on the local keyboard (you can't pass function
  12.   keys through the comport through normal means).  And as long as you follow
  13.   a few simple rules, your procedure will "Multi-Task" WITH the current user
  14.   playing the door, meaning that the user won't even know your using a
  15.   function key procedure!
  16.   -But like i said, thats only if you follow a few rules, and in some cases
  17.   you won't want it to "Multi-Task".
  18.  
  19.   A maximum of 32 procedures can be assigned at one time. (you can change
  20.   that by changing the max_tasks const in the MTASK unit; you will have
  21.   to recompile, ofcourse)... But the more TASKS you create the more HEAP
  22.   is taken.  BTW: when setting up a procedure, the StackSize variable needed
  23.   is the amount of HEAP the procedure will take for its stack+procedure size,
  24.   BUT that space is NOT taken from the heap until the procedure gets called.
  25.   So don't worry about creating 12 procedures, each requiring 5k.  Most of
  26.   the time you will only call 1 of the SysKeys at a time, so only 5k will be
  27.   used at one time.
  28.  
  29.   1) In order for your procedure to Multi-Task with the user you must
  30.      use a procedure called: "switch_task()".  If your procedure is
  31.      small and it doesn't have to get any input from the sysop then
  32.      you probably don't even need to call it, even if the user does get
  33.      a small delay, he/she will just think it was line noise or something.
  34.      But for larger procedures that take a little time to complete you
  35.      will want to call it a couple times.  Or if the procedure needs to
  36.      get input from the sysop then that is the best time to call
  37.      Switch_Task.  Make a simple repeat..until loop like:
  38.        repeat Switch_task until keypressed; (*LOCAL keypress routine*)
  39.      (it might be a good idea to add a counter to that loop so that it
  40.      only switches like every 100 or so interations)
  41.  
  42.      If the procedure is supposed to interact with the sysop AND the user
  43.      then you should not call Switch_Task, there's no need, and the input
  44.      would interfere with the user's game. (as long as you use the "sio"
  45.      input/output routines everything will be fine, since they will switch
  46.      tasks when needed)
  47.  
  48.      One major limitation you should remember is that the Multi-Task
  49.      abilities of this unit are limited to INSIDE your program.  If
  50.      you call any outside programs (ie: shell to dos) then everything
  51.      in the door stops until you return from the external program.
  52.  
  53.   2) The procedure you create must be of the same type as "KeyProc" below.
  54.      The procedure has 1 Untyped variable as a parameter.  When the
  55.      procedure is called, the key that activated it will be sent in the
  56.      parameter.  To use it you have to Typecast it as a CHAR (or some
  57.      other type if you need to) like this:
  58.        procedure mykeyF5(var param); far;
  59.        var key:char absolute param;
  60.        begin
  61.        end;
  62.      The above is the easist way to do it, but not the only way.
  63.      The reason the param is UNTYPED is because thats how MTASK is setup,
  64.      and i can't change it...
  65.  
  66.   3) The procedure you create must be FAR.  Look in the above example
  67.      and notice the word "far" in the procedure header, thats one way of
  68.      doing it.
  69.  
  70.   4) The procedure you create should only use normal write routines so that
  71.      the text written is only displayed locally... (unless the procedure
  72.      you have setup is supposed to be displayed remotely).  The same goes
  73.      for the Readkey type functions.  The DOORIO unit has "WriteStr()" proc.
  74.      that is perfect for this.  It uses direct screen writes, so the cursor
  75.      will not move, and the user's color will not get messed up.
  76.  
  77.   5) The procedure you create must not be in a unit that is being OVERLAYED!
  78.      That would be bad...  And most of the procedures that get created for
  79.      function keys are so small that they really don't need to be overlayed.
  80.  
  81.   6) Some global variables should be saved then altered while in the
  82.      procedure... and then restored right before the procedure exits.
  83.        Door.UpdateLocal:=False;
  84.          This one is optional.  It really depends on what the procedure does.
  85.        Door.LocalInputON:=False;
  86.          If the procedure requires input from the sysop, then this should
  87.          be set to false, so that the COMMIO routines won't intercept
  88.          the sysop's keypresses while IN the sysop function (unless the
  89.          procedure is a CHAT type procedure).
  90.        Syskey1[key].open:=False;
  91.          Right before your procedure exits you _MUST_ set the variable
  92.          above to false.  This will allow you to call this procedure
  93.          again. If you don't set it to false, then you won't be able to
  94.          call that procedure again, until the door is rerun.  You MUST
  95.          besure to use the correct "Syskey??" variable though!  There
  96.          are four different arrays for holding the key procedures.
  97.          Just look at the ranges in the arrays below.
  98.  
  99.   7) I've figured out a crude way to figure out how big a procedure is.
  100.      Create the procedure just like i said above.  Then DIRECTLY AFTER the
  101.      procedure (right after the "end;"), put a VARiable of type word. like
  102.      this:
  103.        procedure MyTask(var p); far;
  104.        begin
  105.          <your code here>
  106.        end;
  107.        var MyTask_size:word;
  108.      Do not make it a const (ie: const MyTask:word=0;), that will NOT work.
  109.      Because TP will move the variable to a different location (it groups
  110.      all initialized consts to the data segment; but the VAR will be right
  111.      where you declare it, in the code segment).
  112.      Then later sometime before you call "create_task()" do the following
  113.      calculation on the MyTask_size var:
  114.        MyTask_size:=ofs(MyTask_size) - ofs(@MyTask^) + 512;
  115.      I add the 512 for safety.  This ONLY gives you the size of the procedure
  116.      ITSELF... the STACKSIZE parameter is the size of the procedure+all stack
  117.      needed by the procedure.  So for every procedure/function inside your
  118.      syskey procedure, you should add more to the stacksize parameter.  Its
  119.      just trial and error... i dont know any other way to figure it out,
  120.      exactly.
  121.  
  122. }
  123. interface
  124.  
  125. uses _input,mtask;
  126.  
  127. const
  128.   F1 = #59; F2 = #60; F3 = #61; F4 = #62; F5 = #63;  F6 = #64;
  129.   F7 = #65; F8 = #66; F9 = #67; F10= #68; F11= #133; F12= #134;
  130.   AltF1 = #104; AltF2  = #105; AltF3  = #106; AltF4  = #107;
  131.   AltF5 = #108; AltF6  = #109; AltF7  = #110; AltF8  = #111;
  132.   AltF9 = #112; AltF10 = #113; AltF11 = #139; AltF12 = #140;
  133. {^ These are all the keys you can create procedures for. }
  134.  
  135. type
  136.   KeyProc = procedure(var param);
  137.   TKeyRec = record
  138.     proc : KeyProc;
  139.     size : integer;
  140.     open : boolean;
  141.     key  : char;
  142.   end;
  143.  
  144. const
  145.   NumProcs : byte = 0;     {how many procedures have been created}
  146.  
  147. var
  148.   SysKey1  : array[F1..F10] of TKeyrec;
  149.   SysKey2  : array[F11..F12] of TKeyrec;
  150.   SysKey1a : array[AltF1..AltF10] of TKeyrec;
  151.   SysKey2a : array[AltF11..AltF12] of TKeyrec;
  152.  
  153. Function SetSysopKey(key:char; proc:KeyProc; stacksize:integer):boolean;
  154. {^ Sets a function key for the sysop to use locally. Returns true or false
  155.    if it was successful.
  156.      key = Which Key to reprogram, valid values are F1..F12, AltF1..AltF12.
  157.      stacksize = How much memory the procedure needs (this is not just STACK
  158.                  for the proc. This is memory for the entire procedure).
  159.                  The minimum is 512k, but most procedures will need more.
  160.      proc = The procedure that gets called.  If "NIL" is passed as the proc
  161.             then that key procedure is removed. }
  162. Procedure RemoveKey(key:char);
  163. {^ Remove a key procedure.  This is just like if you passed "nil" to the
  164.    above proc... th